home *** CD-ROM | disk | FTP | other *** search
/ CD Player 1 / CD Player - Numero 1 (France).7z / CD Player - Numero 1 (France).bin / mpc.c < prev    next >
C/C++ Source or Header  |  1995-01-15  |  35KB  |  1,491 lines

  1. #include <conio.h>  /* _getch, ... */
  2. #include <stdio.h>  /* SEEK_SET, ... */
  3. #include <io.h>     /* _open, _read, _fseek, _close, ...*/
  4. #include <fcntl.h>  /* _O_RDONLY, ... */
  5. #include <graph.h>  /* _setvideomoderows, ... */
  6. #include <memory.h>
  7. #include <malloc.h>
  8. #include <dos.h>
  9. #include <string.h>
  10. #include <process.h>
  11. #include <direct.h> /* _chdir */
  12. #include "TYPES.H"
  13. #include "MPC.H"
  14.  
  15. int CONFileHandle;
  16. BYTE CONFileName[FILENAME_SIZE];
  17. BYTE WARNINGFileName[FILENAME_SIZE];
  18. BYTE BCKFileName[FILENAME_SIZE];
  19. BYTE WINFileName[FILENAME_SIZE];
  20. BYTE ABOUTFileName[FILENAME_SIZE];
  21. BYTE INTROFileName[FILENAME_SIZE];
  22. WORD *pWINData, *pABOUTData;
  23.  
  24. /***************************************************************************/
  25.  
  26. void BlinkOff ()
  27. {
  28.   union _REGS InRegs, OutRegs;
  29.  
  30.   InRegs.h.ah = 0x10;
  31.   InRegs.h.al = 0x03;
  32.   InRegs.h.bl = 0x00;
  33.   _int86 (0x10, &InRegs, &OutRegs);
  34.  
  35.   return;
  36. }
  37.  
  38. /***************************************************************************/
  39.  
  40. void BlinkOn ()
  41. {
  42.   union _REGS InRegs, OutRegs;
  43.  
  44.   InRegs.h.ah = 0x10;
  45.   InRegs.h.al = 0x03;
  46.   InRegs.h.bl = 0x01;
  47.   _int86 (0x10, &InRegs, &OutRegs);
  48.  
  49.   return;
  50. }
  51.  
  52. /***************************************************************************/
  53.  
  54. void HideCursor ()
  55. {
  56.   union _REGS InRegs, OutRegs;
  57.  
  58.   InRegs.h.ah = 0x01;
  59.   InRegs.h.ch = 0x20;
  60.   _int86 (0x10, &InRegs, &OutRegs);
  61.  
  62.   return;
  63. }
  64.  
  65. /***************************************************************************/
  66.  
  67. void ShowCursor ()
  68. {
  69.   union _REGS InRegs, OutRegs;
  70.  
  71.   InRegs.h.ah = 0x01;
  72.   InRegs.x.cx = 0x0607;
  73.   _int86 (0x10, &InRegs, &OutRegs);
  74.  
  75.   return;
  76. }
  77.  
  78. /***************************************************************************/
  79.  
  80. void InitMouse (WORD DX, WORD DY)
  81. {
  82.   union _REGS InRegs, OutRegs;
  83.  
  84.   InRegs.x.ax = 0x0000;
  85.   _int86 (0x33, &InRegs, &OutRegs);
  86.   InRegs.x.ax = 0x0007;
  87.   InRegs.x.cx = 0x0000;
  88.   InRegs.x.dx = DX - 1;
  89.   _int86 (0x33, &InRegs, &OutRegs);
  90.   InRegs.x.ax = 0x0008;
  91.   InRegs.x.cx = 0x0000;
  92.   InRegs.x.dx = DY - 1;
  93.   _int86 (0x33, &InRegs, &OutRegs);
  94.  
  95.   return;
  96. }
  97.  
  98. /***************************************************************************/
  99.  
  100. void ShowMouse ()
  101. {
  102.   union _REGS InRegs, OutRegs;
  103.  
  104.   InRegs.x.ax = 0x0001;
  105.   _int86 (0x33, &InRegs, &OutRegs);
  106.  
  107.   return;
  108. }
  109.  
  110. /***************************************************************************/
  111.  
  112. void HideMouse ()
  113. {
  114.   union _REGS InRegs, OutRegs;
  115.  
  116.   InRegs.x.ax = 0x0002;
  117.   _int86 (0x33, &InRegs, &OutRegs);
  118.  
  119.   return;
  120. }
  121.  
  122. /***************************************************************************/
  123.  
  124. void PutMouse (WORD X, WORD Y)
  125. {
  126.   union _REGS InRegs, OutRegs;
  127.  
  128.   InRegs.x.ax = 0x0004;
  129.   InRegs.x.cx = X;
  130.   InRegs.x.dx = Y;
  131.   _int86 (0x33, &InRegs, &OutRegs);
  132.  
  133.   return;
  134. }
  135.  
  136. /***************************************************************************/
  137.  
  138. WORD GetMouseX ()
  139. {
  140.   union _REGS InRegs, OutRegs;
  141.  
  142.   InRegs.x.ax = 0x0003;
  143.   _int86 (0x33, &InRegs, &OutRegs);
  144.  
  145.   return (OutRegs.x.cx);
  146. }
  147.  
  148. /***************************************************************************/
  149.  
  150. WORD GetMouseY ()
  151. {
  152.   union _REGS InRegs, OutRegs;
  153.  
  154.   InRegs.x.ax = 0x0003;
  155.   _int86 (0x33, &InRegs, &OutRegs);
  156.  
  157.   return (OutRegs.x.dx);
  158. }
  159.  
  160. /***************************************************************************/
  161.  
  162. BOOL LeftClick ()
  163. {
  164.   union _REGS InRegs, OutRegs;
  165.  
  166.   InRegs.x.ax = 0x0003;
  167.   _int86 (0x33, &InRegs, &OutRegs);
  168.   if (OutRegs.x.bx == 0x0001)
  169.     return (TRUE);
  170.  
  171.   return (FALSE);
  172. }
  173.  
  174. /***************************************************************************/
  175.  
  176. BOOL RightClick ()
  177. {
  178.   union _REGS InRegs, OutRegs;
  179.  
  180.   InRegs.x.ax = 0x0003;
  181.   _int86 (0x33, &InRegs, &OutRegs);
  182.   if (OutRegs.x.bx == 0x0002)
  183.      return (TRUE);
  184.  
  185.   return (FALSE);
  186. }
  187.  
  188. /****************************************************************************/
  189.  
  190. void WriteBlockFile (int Handle, long Offset, unsigned EOT, WORD X, WORD Y, WORD DX, WORD DY, WORD Col, WORD CHR)
  191. {
  192.   /* Print text (cf WriteBlockText) from file whose handle is Handle starting from
  193.      offset Offset until BYTE EOT is meet */
  194.  
  195.   WORD __huge *pScreen, __huge *pLine;
  196.   BOOL Text;
  197.   BYTE C;
  198.  
  199.   lseek (Handle, Offset, SEEK_SET);
  200.   Text = TRUE;
  201.   pScreen = 0xB8000000 + (((Y*SCREEN_DX) + X) << 1);
  202.   read (Handle, &C, 1);
  203.   while (DY != 0)
  204.   {
  205.     /* Read/write a line */
  206.  
  207.     pLine = pScreen;
  208.     for (X = DX; X != 0; X --)
  209.     {
  210.       if (Text == TRUE)
  211.       {
  212.     if (C == '\n')
  213.     {
  214.       while (X != 0)
  215.       {
  216.         *pLine ++ = Col | CHR;
  217.         X --;
  218.       }
  219.       read (Handle, &C, 1);
  220.       goto NextLine;
  221.     }
  222.     if (C == EOT)
  223.     {
  224.       *pLine ++ = Col | CHR;
  225.       Text = FALSE;
  226.     }
  227.     else
  228.     {
  229.       *pLine ++ = Col | C;
  230.       read (Handle, &C, 1);
  231.     }
  232.       }
  233.       else
  234.     *pLine ++ = Col | CHR;
  235.     }
  236.  
  237.     /* Skip next BYTE if '\n' ending a full width line */
  238.  
  239.     if (Text == TRUE)
  240.     {
  241.       if (C == '\n')
  242.     read (Handle, &C, 1);
  243.     }
  244. NextLine:
  245.     pScreen += SCREEN_DX;
  246.     DY --;
  247.   }
  248. }
  249.  
  250. /****************************************************************************/
  251.  
  252. void WriteBlockText (BYTE *pString, WORD X, WORD Y, WORD DX, WORD DY, WORD Col, WORD CHR)
  253. {
  254.   /* Write the string pointed by pString in the zone (X, Y, DX, DY) using
  255.      text/background colors set as Col. Fill the zone with BYTE CHR if
  256.      zone is not fully filled by the string. If pString == NULL, the zone
  257.      is just cleared */
  258.  
  259.   WORD __huge *pScreen, __huge *pLine;
  260.   BOOL Text;
  261.  
  262.   if ((pString == NULL) || (*pString == '\0'))
  263.     Text = FALSE;
  264.   else
  265.     Text = TRUE;
  266.   pScreen = 0xB8000000 + ((Y*SCREEN_DX + X) << 1);
  267.   while (DY != 0)
  268.   {
  269.     /* Write a line */
  270.  
  271.     pLine = pScreen;
  272.     for (X = DX; X != 0; X --)
  273.     {
  274.       if (Text == TRUE)
  275.       {
  276.     switch (*pString)
  277.     {
  278.       case '\n':
  279.         while (X != 0)
  280.         {
  281.           *pLine ++ = Col | CHR;
  282.           X --;
  283.         }
  284.         goto NextLine;
  285.  
  286.       case '\0':
  287.         *pLine ++ = Col | CHR;
  288.         Text = FALSE;
  289.         break;
  290.  
  291.       default:
  292.         *pLine ++ = Col | *pString ++;
  293.         break;
  294.     }
  295.       }
  296.       else
  297.       *pLine ++ = Col | CHR;
  298.     }
  299.  
  300.     /* Skip next BYTE if '\n' ending a full width line */
  301.  
  302.     if (Text == TRUE)
  303.     {
  304.       if (*pString == '\n')
  305.     pString ++;
  306.     }
  307. NextLine:
  308.     pScreen += SCREEN_DX;
  309.     DY --;
  310.   }
  311.  
  312.   return;
  313. }
  314.  
  315. /****************************************************************************/
  316.  
  317. struct TList *CONSetup (void)
  318. {
  319.   /* Acces to resource CON file and create the equivalent TList/TNode
  320.      structures set. File is *NOT* closed at the end of this call.
  321.      '\n' is considered $0D0A */
  322.  
  323.   struct TNodePARENT *pNodePARENT;
  324.   struct TNodeLIST *pNodeLIST;
  325.   struct TNodeNODE *pNodeNODE;
  326.   struct TNodePICTURE *pNodePICTURE;
  327.   struct TNode *pNode;
  328.   long L;
  329.   struct TList *pListTmp, *pList;
  330.   BYTE C, *pString;
  331.   WORD EndNode, EndList, Size;
  332.  
  333.   /* Initializations */
  334.  
  335.   CONFileHandle = _open (CONFileName, _O_RDONLY);
  336.   pList = malloc (sizeof (struct TList));
  337.   pList->Head = NULL;
  338.   pList->Pred = NULL;
  339.   pNode = NULL;
  340.  
  341.   /* Decrypt loop */
  342.  
  343.   for (;;)
  344.   {
  345.     do
  346.       read (CONFileHandle, &C, 1);
  347.     while (C != '[');
  348.     read (CONFileHandle, &L, 4);
  349.     switch (L)
  350.     {
  351.       case TAG_PICT:
  352.     lseek (CONFileHandle, 3, SEEK_CUR);
  353.     if (pList->Head != NULL)
  354.     {
  355.       pNodePICTURE = malloc (sizeof (struct TNodePICTURE));
  356.       pNode->Succ = (struct TNode *) pNodePICTURE;
  357.       pNodePICTURE->Node.Pred = pNode;
  358.     }
  359.     else
  360.     {
  361.       pNodePICTURE = malloc (sizeof (struct TNodePICTURE));
  362.       pNodePICTURE->Node.Pred = NULL;
  363.       pList->Head = &(pNodePICTURE->Node);
  364.     }
  365.     pNodePICTURE->Node.Succ = NULL;
  366.     pNodePICTURE->Node.Type = TYPE_PICTURE;
  367.     pNodePICTURE->OfsLDes = - 1;
  368.     pNodePICTURE->OfsSDes = - 1;
  369.     pNodePICTURE->pFileName = NULL;
  370.     EndNode = FALSE;
  371.     while (EndNode == FALSE)
  372.     {
  373.       do
  374.         read (CONFileHandle, &C, 1);
  375.       while (C != '<');
  376.       read (CONFileHandle, &L, 4);
  377.       switch (L)
  378.       {
  379.         case TAG_NAME:
  380.           lseek (CONFileHandle, 3, SEEK_CUR);
  381.           pNodePICTURE->Node.pName = malloc (NAME_SIZE);
  382.           pString = pNodePICTURE->Node.pName;
  383.           read (CONFileHandle, &C, 1);
  384.           for (Size = NAME_SIZE; Size > 1; Size --)
  385.           {
  386.         if (C == '\n')
  387.           break;
  388.         *pString ++ = C;
  389.         read (CONFileHandle, &C, 1);
  390.           }
  391.           *pString = '\0';
  392.           break;
  393.  
  394.         case TAG_SDES:
  395.           lseek (CONFileHandle, 3, SEEK_CUR);
  396.           pNodePICTURE->OfsSDes = _tell (CONFileHandle);
  397.           break;
  398.  
  399.         case TAG_LDES:
  400.           lseek (CONFileHandle, 3, SEEK_CUR);
  401.           pNodePICTURE->OfsLDes = _tell (CONFileHandle);
  402.           break;
  403.  
  404.         case TAG_FILE:
  405.           lseek (CONFileHandle, 3, SEEK_CUR);
  406.           pNodePICTURE->pFileName = malloc (FILENAME_SIZE);
  407.           pString = pNodePICTURE->pFileName;
  408.           read (CONFileHandle, &C, 1);
  409.           for (Size = FILENAME_SIZE; Size > 1; Size --)
  410.           {
  411.         if (C == '\n')
  412.           break;
  413.         *pString ++ = C;
  414.         read (CONFileHandle, &C, 1);
  415.           }
  416.           *pString = '\0';
  417.           break;
  418.  
  419.         case TAG_DONE:
  420.           lseek (CONFileHandle, 3, SEEK_CUR);
  421.           EndNode = TRUE;
  422.           break;
  423.  
  424.         default:
  425. /* Should report error and freem all allocated memory */
  426.           break;
  427.       }
  428.       pNode = &(pNodePICTURE->Node);
  429.     }
  430.     break;
  431.  
  432.       case TAG_NODE:
  433.     lseek (CONFileHandle, 3, SEEK_CUR);
  434.     if (pList->Head != NULL)
  435.     {
  436.       pNodeNODE = malloc (sizeof (struct TNodeNODE));
  437.       pNode->Succ = (struct TNode *) pNodeNODE;
  438.       pNodeNODE->Node.Pred = pNode;
  439.     }
  440.     else
  441.     {
  442.       pNodeNODE =  malloc (sizeof (struct TNodeNODE));
  443.       pNodeNODE->Node.Pred = NULL;
  444.       pList->Head = &(pNodeNODE->Node);
  445.     }
  446.     pNodeNODE->Node.Succ = NULL;
  447.     pNodeNODE->Node.Type = TYPE_NODE;
  448.     pNodeNODE->OfsLDes = - 1;
  449.     pNodeNODE->OfsSDes = - 1;
  450.     pNodeNODE->OfsCMDS = - 1;
  451.     EndNode = FALSE;
  452.     while (EndNode == FALSE)
  453.     {
  454.       do
  455.         read (CONFileHandle, &C, 1);
  456.       while (C != '<');
  457.       read (CONFileHandle, &L, 4);
  458.       switch (L)
  459.       {
  460.         case TAG_NAME:
  461.           lseek (CONFileHandle, 3, SEEK_CUR);
  462.           pNodeNODE->Node.pName = malloc (NAME_SIZE);
  463.           pString = pNodeNODE->Node.pName;
  464.           read (CONFileHandle, &C, 1);
  465.           for (Size = NAME_SIZE; Size > 1; Size --)
  466.           {
  467.         if (C == '\n')
  468.           break;
  469.         *pString ++ = C;
  470.         read (CONFileHandle, &C, 1);
  471.           }
  472.           *pString = '\0';
  473.           break;
  474.  
  475.         case TAG_SDES:
  476.           lseek (CONFileHandle, 3, SEEK_CUR);
  477.           pNodeNODE->OfsSDes = _tell (CONFileHandle);
  478.           break;
  479.  
  480.         case TAG_LDES:
  481.           lseek (CONFileHandle, 3, SEEK_CUR);
  482.           pNodeNODE->OfsLDes = _tell (CONFileHandle);
  483.           break;
  484.  
  485.         case TAG_CMDS:
  486.           lseek (CONFileHandle, 3, SEEK_CUR);
  487.           pNodeNODE->OfsCMDS = _tell (CONFileHandle);
  488.           break;
  489.  
  490.         case TAG_DONE:
  491.           lseek (CONFileHandle, 3, SEEK_CUR);
  492.           EndNode = TRUE;
  493.           break;
  494.  
  495.         default:
  496. /* Should report error and freem all allocated memory */
  497.           break;
  498.       }
  499.       pNode = &(pNodeNODE->Node);
  500.     }
  501.     break;
  502.  
  503.       case TAG_LIST:
  504.     lseek (CONFileHandle, 3, SEEK_CUR);
  505.     if (pList->Head != NULL)
  506.     {
  507.       pNodeLIST = malloc (sizeof (struct TNodeLIST));
  508.       pNode->Succ = (struct TNode *) pNodeLIST;
  509.       pNodeLIST->Node.Pred = pNode;
  510.     }
  511.     else
  512.     {
  513.       pNodeLIST = malloc (sizeof (struct TNodeLIST));
  514.       pNodeLIST->Node.Pred = NULL;
  515.       pList->Head = &(pNodeLIST->Node);
  516.     }
  517.     pNodeLIST->Node.Succ = NULL;
  518.     pNodeLIST->Node.Type = TYPE_LIST;
  519.     pNodeLIST->OfsLDes = - 1;
  520.     pNodeLIST->OfsSDes = - 1;
  521.     EndList = FALSE;
  522.     while (EndList == FALSE)
  523.     {
  524.       do
  525.         read (CONFileHandle, &C, 1);
  526.       while (C !='<');
  527.       read (CONFileHandle, &L, 4);
  528.       switch (L)
  529.       {
  530.         case TAG_NAME:
  531.           lseek (CONFileHandle, 3, SEEK_CUR);
  532.           pNodeLIST->Node.pName = malloc (NAME_SIZE);
  533.           pString = pNodeLIST->Node.pName;
  534.           read (CONFileHandle, &C, 1);
  535.           for (Size = NAME_SIZE; Size > 1; Size --)
  536.           {
  537.         if (C == '\n')
  538.           break;
  539.         *pString ++ = C;
  540.         read (CONFileHandle, &C, 1);
  541.           }
  542.           *pString = '\0';
  543.           break;
  544.  
  545.         case TAG_SDES:
  546.           lseek (CONFileHandle, 3, SEEK_CUR);
  547.           pNodeLIST->OfsSDes = _tell (CONFileHandle);
  548.           break;
  549.  
  550.         case TAG_LDES:
  551.           lseek (CONFileHandle, 3, SEEK_CUR);
  552.           pNodeLIST->OfsLDes = _tell (CONFileHandle);
  553.           break;
  554.  
  555.         case TAG_LIST:
  556.           lseek (CONFileHandle, 3, SEEK_CUR);
  557.           EndList = TRUE;
  558.           break;
  559.  
  560.         default:
  561. /* Should report error and freem all allocated memory */
  562.           break;
  563.       }
  564.     }
  565.  
  566.     /* Create a new list in the list of lists */
  567.  
  568.     pListTmp = malloc (sizeof (struct TList));
  569.     pListTmp->Pred = pList;
  570.     pList = pListTmp;
  571.     pNodeLIST->pList = pList;
  572.  
  573.     /* Create the first node of the list as a TNodePARENT structure */
  574.  
  575.     pNodePARENT = malloc (sizeof (struct TNodePARENT));
  576.     pNodePARENT->Node.Succ = NULL;
  577.     pNodePARENT->Node.Pred = NULL;
  578.     pNodePARENT->Node.Type = TYPE_PARENT;
  579.     pNodePARENT->Node.pName = malloc (NAME_SIZE);
  580.     strcpy (pNodePARENT->Node.pName, PARENT);
  581.     pList->Head = (struct TNode *) pNodePARENT;
  582.  
  583.     pNode = &(pNodePARENT->Node);
  584.     break;
  585.  
  586.       case TAG_DONE:
  587.     lseek (CONFileHandle, 3, SEEK_CUR);
  588.     if (pList->Pred == NULL)
  589.       return (pList);
  590.     pList = pList->Pred;
  591.     pNode = pList->Head;
  592.     while (pNode->Succ != NULL)
  593.       pNode = pNode->Succ;
  594.     break;
  595.  
  596.       default:
  597. /* Should report error and freem all allocated memory */
  598.     break;
  599.     }
  600.   }
  601. }
  602.  
  603. /****************************************************************************/
  604.  
  605. void Introduction (void)
  606. {
  607.   /* Read background ASC file and draw menu
  608.      Read window ASC file in an allocated memory area
  609.      Read about ASC file in an allocated memory area*/
  610.  
  611.   int Handle;
  612.   WORD *pBuffer, S;
  613.   BYTE C, Cmd[255];
  614.   WORD __huge *pScreen;
  615.  
  616.   /* Video setup */
  617.  
  618.   _setvideomoderows (_TEXTC80, SCREEN25_DY);
  619.   HideCursor ();
  620.   BlinkOff ();
  621.  
  622.   /* Read warning file and display it */
  623.  
  624.   Handle = _open (WARNINGFileName, _O_RDONLY);
  625.   pBuffer = malloc ((SCREEN_DX*SCREEN25_DY) << 1);
  626.   lseek (Handle, 8, SEEK_SET);
  627.   read (Handle, pBuffer, (SCREEN_DX*SCREEN25_DY) << 1);
  628.   pScreen = 0xB8000000;
  629.   for (S = (SCREEN_DX*SCREEN25_DY) << 1; S != 0; S --)
  630.     *pScreen ++ = *pBuffer ++;
  631.   free (pBuffer);
  632.   close (Handle);
  633.   C = _getch ();
  634.   while ((C != KEY_RETURN) && (C != KEY_ESC))
  635.     _getch ();
  636.   _clearscreen (_GCLEARSCREEN);
  637.  
  638.   /* Diplay intro picture */
  639.  
  640.   strcpy (Cmd, PICEM);
  641.   strcat (Cmd, INTROFileName);
  642.   system (Cmd);
  643.  
  644.   /* Video setup */
  645.  
  646.   _setvideomoderows (_TEXTC80, SCREEN50_DY);
  647.   HideCursor ();
  648.   BlinkOff ();
  649.  
  650.   /* Read background file and display it */
  651.  
  652.   Handle = _open (BCKFileName, _O_RDONLY);
  653.   pBuffer = malloc ((SCREEN_DX*SCREEN50_DY) << 1);
  654.   lseek (Handle, 8, SEEK_SET);
  655.   read (Handle, pBuffer, (SCREEN_DX*(SCREEN50_DY-1)) << 1);
  656.   pScreen = 0xB8000000+(SCREEN_DX << 1);
  657.   for (S = (SCREEN_DX*(SCREEN50_DY-1)) << 1; S != 0; S --)
  658.     *pScreen ++ = *pBuffer ++;
  659.   free (pBuffer);
  660.   close (Handle);
  661.  
  662.   /* Allocate memory and read window file */
  663.  
  664.   Handle = _open (WINFileName, _O_RDONLY);
  665.   pWINData = malloc ((LDES_DX*LDES_DY) << 1);
  666.   lseek (Handle, 8, SEEK_SET);
  667.   read (Handle, pWINData, (LDES_DX*LDES_DY) << 1);
  668.   close (Handle);
  669.  
  670.   /* Allocate memory and read window file */
  671.  
  672.   Handle = _open (ABOUTFileName, _O_RDONLY);
  673.   pABOUTData = malloc ((ABOUT_DX*ABOUT_DY) << 1);
  674.   lseek (Handle, 8, SEEK_SET);
  675.   read (Handle, pABOUTData, (ABOUT_DX*ABOUT_DY) << 1);
  676.   close (Handle);
  677.  
  678.   return;
  679. }
  680.  
  681. /****************************************************************************/
  682.  
  683. struct TNode *DestroyNodePICTURE (struct TNodePICTURE *pNodePICTURE)
  684. {
  685.   struct TNode *pNode;
  686.  
  687.   free (pNodePICTURE->Node.pName);
  688.   free (pNodePICTURE->pFileName);
  689.   pNode = pNodePICTURE->Node.Succ;
  690.   free (pNodePICTURE);
  691.  
  692.   return (pNode);
  693. }
  694.  
  695. /****************************************************************************/
  696.  
  697. struct TNode *DestroyNodeNODE (struct TNodeNODE *pNodeNODE)
  698. {
  699.   struct TNode *pNode;
  700.  
  701.   free (pNodeNODE->Node.pName);
  702.   pNode = pNodeNODE->Node.Succ;
  703.   free (pNodeNODE);
  704.  
  705.   return (pNode);
  706. }
  707.  
  708. /****************************************************************************/
  709.  
  710. struct TNode *DestroyNodeLIST (struct TNodeLIST *pNodeLIST)
  711. {
  712.   struct TNode *pNode;
  713.  
  714.   free (pNodeLIST->Node.pName);
  715.   pNode = pNodeLIST->Node.Succ;
  716.   free (pNodeLIST);
  717.  
  718.   return (pNode);
  719. }
  720.  
  721. /****************************************************************************/
  722.  
  723. struct TNode *DestroyNodePARENT (struct TNodePARENT *pNodePARENT)
  724. {
  725.   struct TNode *pNode;
  726.  
  727.   free (pNodePARENT->Node.pName);
  728.   pNode = pNodePARENT->Node.Succ;
  729.   free (pNodePARENT);
  730.  
  731.   return (pNode);
  732. }
  733.  
  734. /****************************************************************************/
  735.  
  736. void DestroyList (struct TList *pList)
  737. {
  738.   /* Recusive function destroying all nodes and TList structure found in
  739.      the walk of the provided TList structure */
  740.  
  741.   struct TNode *pNode;
  742.  
  743.   pNode = pList->Head;
  744.   while (pNode != NULL)
  745.   {
  746.     switch (pNode->Type)
  747.     {
  748.       case TYPE_PICTURE:
  749.     pNode = DestroyNodePICTURE ((struct TNodePICTURE *) pNode);
  750.     break;
  751.  
  752.       case TYPE_NODE:
  753.     pNode = DestroyNodeNODE ((struct TNodeNODE *) pNode);
  754.     break;
  755.  
  756.       case TYPE_PARENT:
  757.     pNode = DestroyNodePARENT ((struct TNodePARENT *) pNode);
  758.     break;
  759.  
  760.       case TYPE_LIST:
  761.     DestroyList (((struct TNodeLIST *) pNode)->pList);
  762.     pNode = DestroyNodeLIST ((struct TNodeLIST *) pNode);
  763.     break;
  764.     }
  765.   }
  766.   free (pList);
  767.  
  768.   return;
  769. }
  770.  
  771. /****************************************************************************/
  772.  
  773. void DrawList (struct TNode *pNode)
  774. {
  775.   /* Clear and refresh list content using the list of node starting from
  776.      the provided TNode parameter */
  777.  
  778.   BYTE Y;
  779.  
  780.   for (Y = LV_Y; Y != LV_Y + LV_DY; Y ++)
  781.   {
  782.     if (pNode != NULL)
  783.     {
  784.       WriteBlockText (pNode->pName, LV_X + 1, Y, LV_DX - 2, 1, COL_LV, CHR_LV);
  785.       pNode = pNode->Succ;
  786.     }
  787.     else
  788.       WriteBlockText (NULL, LV_X + 1, Y, LV_DX - 2, 1, COL_LV, CHR_LV);
  789.   }
  790.  
  791.   return;
  792. }
  793.  
  794. /****************************************************************************/
  795.  
  796. void DrawSelect (struct TNode *pNode, WORD Select, struct TNode *pOldNode, WORD OldSelect)
  797. {
  798.   /* Make visual selection of entry pNode, index Select in the listview
  799.      Display short description related to pNode
  800.      Make visual deselection of entry pOldNode, index OldSelect in the
  801.      listview.
  802.      It is possible to call DrawSelect (NULL, 0, pNode, ?) or
  803.      DrawSelect (pNode, 0, pNode, ?) to perform just a selection or just
  804.      a deselection */
  805.  
  806.  
  807.   /* Unselect */
  808.  
  809.   if (pOldNode != NULL)
  810.   {
  811.     WriteBlockText (NULL, LV_X, LV_Y + OldSelect, 1, 1, COL_LV, CHR_LV);
  812.     WriteBlockText (NULL, LV_X + LV_DX - 1, LV_Y + OldSelect, 1, 1, COL_LV, CHR_LV);
  813.     WriteBlockText (pOldNode->pName, LV_X + 1, LV_Y + OldSelect, LV_DX - 2, 1, COL_LV, CHR_LV);
  814.   }
  815.  
  816.   /* Select */
  817.  
  818.   if (pNode != NULL)
  819.   {
  820.     WriteBlockText (NULL, LV_X, LV_Y + Select, 1, 1, COL_LVSEL, CHR_LVSEL);
  821.     WriteBlockText (NULL, LV_X + LV_DX - 1, LV_Y + Select, 1, 1, COL_LVSEL, CHR_LVSEL);
  822.     WriteBlockText (pNode->pName, LV_X + 1, LV_Y + Select, LV_DX - 2, 1, COL_LVSEL, CHR_LVSEL);
  823.  
  824.     /* Display short description if any (always clear old short description) */
  825.  
  826.     switch (pNode->Type)
  827.     {
  828.       case TYPE_PICTURE:
  829.     if (((struct TNodePICTURE *) pNode)->OfsSDes != - 1)
  830.       WriteBlockFile (CONFileHandle, ((struct TNodePICTURE *) pNode)->OfsSDes, '<', SDES_X, SDES_Y, SDES_DX, SDES_DY, COL_SDES, CHR_SDES);
  831.     else
  832.       WriteBlockText (NULL, SDES_X, SDES_Y, SDES_DX, SDES_DY, COL_SDES, CHR_SDES);
  833.     break;
  834.  
  835.       case TYPE_NODE:
  836.     if (((struct TNodeNODE *) pNode)->OfsSDes != - 1)
  837.       WriteBlockFile (CONFileHandle, ((struct TNodeNODE *) pNode)->OfsSDes, '<', SDES_X, SDES_Y, SDES_DX, SDES_DY, COL_SDES, CHR_SDES);
  838.     else
  839.       WriteBlockText (NULL, SDES_X, SDES_Y, SDES_DX, SDES_DY, COL_SDES, CHR_SDES);
  840.     break;
  841.  
  842.       case TYPE_LIST:
  843.     if (((struct TNodeLIST *) pNode)->OfsSDes != - 1)
  844.       WriteBlockFile (CONFileHandle, ((struct TNodeLIST *) pNode)->OfsSDes, '<', SDES_X, SDES_Y, SDES_DX, SDES_DY, COL_SDES, CHR_SDES);
  845.     else
  846.       WriteBlockText (NULL, SDES_X, SDES_Y, SDES_DX, SDES_DY, COL_SDES, CHR_SDES);
  847.     break;
  848.  
  849.       default:
  850.     WriteBlockText (NULL, SDES_X, SDES_Y, SDES_DX, SDES_DY, COL_SDES, CHR_SDES);
  851.     }
  852.   }
  853.  
  854.   return;
  855. }
  856.  
  857. /****************************************************************************/
  858.  
  859. WORD *GetImage (WORD X, WORD Y, WORD DX, WORD DY)
  860. {
  861.   /* Allocate a buffer and save image into it */
  862.  
  863.   WORD *pData, *pDataTmp;
  864.   WORD __huge *pScreen;
  865.  
  866.   pData = malloc (DX*DY << 1);
  867.   pDataTmp = pData;
  868.   pScreen = 0xB8000000 + ((Y*SCREEN_DX + X) << 1);
  869.   while (DY != 0)
  870.   {
  871.     for (X = DX; X != 0; X --)
  872.       *pDataTmp ++ = *pScreen ++;
  873.     pScreen += SCREEN_DX - DX;
  874.     DY --;
  875.   }
  876.  
  877.   return (pData);
  878. }
  879.  
  880. /****************************************************************************/
  881.  
  882. void PutImage (WORD X, WORD Y, WORD DX, WORD DY, WORD *pData)
  883. {
  884.   /* Draw image and free buffer */
  885.  
  886.   WORD *pDataTmp;
  887.   WORD __huge *pScreen;
  888.  
  889.   pDataTmp = pData;
  890.   pScreen = 0xB8000000 + ((Y*SCREEN_DX + X) << 1);
  891.   while (DY != 0)
  892.   {
  893.     for (X = DX; X != 0; X --)
  894.       *pScreen ++ = *pDataTmp ++;
  895.  
  896.     pScreen += SCREEN_DX - DX;
  897.     DY --;
  898.   }
  899.   free (pData);
  900.  
  901.   return;
  902. }
  903.  
  904. /****************************************************************************/
  905.  
  906. void DrawLDes (struct TNode *pNode)
  907. {
  908.   /* Display long description of entry pNode, if any */
  909.  
  910.   WORD __huge *pScreen;
  911.   WORD *pData, *pBuffer, X, Y;
  912.   BYTE C;
  913.  
  914.   switch (pNode->Type)
  915.   {
  916.     case TYPE_LIST:
  917.       if (((struct TNodeLIST *) pNode)->OfsLDes != -1)
  918.       {
  919.     pBuffer = GetImage (LDES_X, LDES_Y, LDES_DX, LDES_DY);
  920.     pScreen = 0xB8000000 + ((SCREEN_DX*LDES_Y + LDES_X) << 1);
  921.     pData = pWINData;
  922.     for (Y = LDES_DY; Y != 0; Y --)
  923.     {
  924.       for (X = LDES_DX; X != 0; X --)
  925.       {
  926.         *pScreen ++ = *pData ++;
  927.       }
  928.       pScreen += SCREEN_DX - LDES_DX;
  929.     }
  930.     WriteBlockFile (CONFileHandle, ((struct TNodeLIST *) pNode)->OfsLDes, '<', LDES_X + 1, LDES_Y + 2, LDES_DX - 3, LDES_DY - 5, COL_LDES, CHR_LDES);
  931.  
  932.     while ((C = _getch ()) != KEY_RETURN)
  933.       ;
  934.     PutImage (LDES_X, LDES_Y, LDES_DX, LDES_DY, pBuffer);
  935.       }
  936.       break;
  937.  
  938.     case TYPE_NODE:
  939.       if (((struct TNodeNODE *) pNode)->OfsLDes != -1)
  940.       {
  941.     pBuffer = GetImage (LDES_X, LDES_Y, LDES_DX, LDES_DY);
  942.     pScreen = 0xB8000000 + ((SCREEN_DX*LDES_Y + LDES_X) << 1);
  943.     pData = pWINData;
  944.     for (Y = LDES_DY; Y != 0; Y --)
  945.     {
  946.       for (X = LDES_DX; X != 0; X --)
  947.       {
  948.         *pScreen ++ = *pData ++;
  949.       }
  950.       pScreen += SCREEN_DX - LDES_DX;
  951.     }
  952.     WriteBlockFile (CONFileHandle, ((struct TNodeNODE *) pNode)->OfsLDes, '<', LDES_X + 1, LDES_Y + 2, LDES_DX - 3, LDES_DY - 5, COL_LDES, CHR_LDES);
  953.  
  954.     while ((C = _getch ()) != KEY_RETURN)
  955.       ;
  956.     PutImage (LDES_X, LDES_Y, LDES_DX, LDES_DY, pBuffer);
  957.       }
  958.       break;
  959.  
  960.     default:
  961.       break;
  962.   }
  963.  
  964.   return;
  965. }
  966.  
  967. /****************************************************************************/
  968.  
  969. void About ()
  970. {
  971.   /* Display About requester */
  972.  
  973.   WORD __huge *pScreen;
  974.   WORD *pData, *pBuffer, X, Y;
  975.   BYTE C;
  976.  
  977.   pBuffer = GetImage (ABOUT_X, ABOUT_Y, ABOUT_DX, ABOUT_DY);
  978.   pScreen = 0xB8000000 + ((SCREEN_DX*ABOUT_Y + ABOUT_X) << 1);
  979.   pData = pABOUTData;
  980.   for (Y = ABOUT_DY; Y != 0; Y --)
  981.   {
  982.     for (X = ABOUT_DX; X != 0; X --)
  983.     {
  984.       *pScreen ++ = *pData ++;
  985.     }
  986.     pScreen += SCREEN_DX - ABOUT_DX;
  987.   }
  988.   while ((C = _getch ()) != KEY_RETURN)
  989.     ;
  990.   PutImage (ABOUT_X, ABOUT_Y, ABOUT_DX, ABOUT_DY, pBuffer);
  991.  
  992.   return;
  993. }
  994.  
  995. /****************************************************************************/
  996.  
  997. void Quit (struct TList *pList)
  998. {
  999.   free (pWINData);
  1000.   free (pABOUTData);
  1001.   while (pList->Pred != NULL)
  1002.     pList = pList->Pred;
  1003.   DestroyList (pList);
  1004.   close (CONFileHandle);
  1005.   _setvideomode (_DEFAULTMODE);
  1006.   _clearscreen (_GCLEARSCREEN);
  1007.   BlinkOn ();
  1008.   ShowCursor ();
  1009. }
  1010.  
  1011. /****************************************************************************/
  1012.  
  1013. void Execute (struct TNode *pNode, struct TList *pList)
  1014. {
  1015.   /* Read commands if any and build a list of commands. Execute them */
  1016.  
  1017.   struct TCmdsList *pCmdsList, *pCmdsListTmp;
  1018.   BYTE I, C, MainCmd[COMMAND_SIZE];
  1019.   BYTE *Args[MAX_ARGS + 1], *pString;
  1020.   WORD __huge *pScreen, X;
  1021.  
  1022.   switch (pNode->Type)
  1023.   {
  1024.     case TYPE_PICTURE:
  1025.       if (((struct TNodePICTURE *) pNode)->pFileName != NULL)
  1026.       {
  1027.     strcpy (MainCmd, PICEM);
  1028.     strcat (MainCmd, ((struct TNodePICTURE *) pNode)->pFileName);
  1029.     system (MainCmd);
  1030.     HideCursor ();
  1031.     BlinkOff ();
  1032.     pScreen = 0xB8000000;
  1033.     for (X = SCREEN_DX; X > 0; X --)
  1034.       *pScreen ++ = 0x00DB;
  1035.       }
  1036.       break;
  1037.  
  1038.     case TYPE_NODE:
  1039.       /* Build list of commands */
  1040.  
  1041.       if (((struct TNodeNODE *) pNode)->OfsCMDS == - 1)
  1042.     return;
  1043.       lseek (CONFileHandle, ((struct TNodeNODE *) pNode)->OfsCMDS, SEEK_SET);
  1044.       pCmdsList = NULL;
  1045.       for (;;)
  1046.       {
  1047.     if (pCmdsList == NULL)
  1048.     {
  1049.       pCmdsList = malloc (sizeof (struct TCmdsList));
  1050.       pCmdsList->Succ = NULL;
  1051.       pCmdsList->pCommand = malloc (COMMAND_SIZE);
  1052.       pCmdsListTmp = pCmdsList;
  1053.     }
  1054.     else
  1055.     {
  1056.       pCmdsListTmp->Succ = malloc (sizeof (struct TCmdsList));
  1057.       pCmdsListTmp = pCmdsListTmp->Succ;
  1058.       pCmdsListTmp->Succ = NULL;
  1059.       pCmdsListTmp->pCommand = malloc (COMMAND_SIZE);
  1060.     }
  1061.  
  1062.     pString = pCmdsListTmp->pCommand;
  1063.     do
  1064.       read (CONFileHandle, pString, 1);
  1065.     while (*pString ++ != '\n');
  1066.     *(pString - 1) = '\0';
  1067.     read (CONFileHandle, &C, 1);
  1068.     if (C == '<')
  1069.       break;
  1070.     else
  1071.       lseek (CONFileHandle, - 1, SEEK_CUR);
  1072.       }
  1073.  
  1074.       /* Execute commands */
  1075.  
  1076.       if (pCmdsList != NULL)
  1077.       {
  1078.     Quit (pList);
  1079.  
  1080.     /* Execute all but last command */
  1081.  
  1082.     while (pCmdsList->Succ != NULL)
  1083.     {
  1084.       system (pCmdsList->pCommand);
  1085.       pCmdsListTmp = pCmdsList;
  1086.       pCmdsList = pCmdsList->Succ;
  1087.       free (pCmdsListTmp->pCommand);
  1088.       free (pCmdsListTmp);
  1089.     }
  1090.  
  1091.     /* Execute last command */
  1092.  
  1093.     strcpy (MainCmd, pCmdsList->pCommand);
  1094.     free (pCmdsList->pCommand);
  1095.     free (pCmdsList);
  1096.     pString = MainCmd;
  1097.     for (I = 0; I < MAX_ARGS; I ++)
  1098.     {
  1099.       Args[I] = pString;
  1100.       while ((*pString != ' ') && (*pString != '\0'))
  1101.     pString ++;
  1102.       if (*pString == '\0')
  1103.     break;
  1104.       else
  1105.     *pString ++ = '\0';
  1106.     }
  1107.     Args[I + 1] = NULL;
  1108.     _execv (Args[0], Args);
  1109.       }
  1110.       break;
  1111.  
  1112.     default:
  1113.       return;
  1114.   }
  1115.  
  1116.   return;
  1117. }
  1118.  
  1119. /****************************************************************************/
  1120.  
  1121. BOOL CheckArgs ()
  1122. {
  1123.   /* Checks the arguments of the command line:
  1124.      - Test if <Warning> is an ASC SCREEN_DX*SCREEN50_DY/2 file
  1125.      - Test if <Background> is an ASC SCREEN_DX*SCREEN50_DY file
  1126.      - Test if <Window> is an ASC LDES_DX*LDES_DY file
  1127.      - Test if <About> is an ASC ABOUT_DX*ABOUT_DY file */
  1128.  
  1129.   int Handle;
  1130.   long L;
  1131.   WORD W;
  1132.  
  1133.   /* Check <Warning> */
  1134.  
  1135.   Handle = _open (WARNINGFileName, _O_RDONLY);
  1136.   if (Handle == - 1)
  1137.   {
  1138.     printf ("Can't open file \"%s\" !\n", WARNINGFileName);
  1139.     return (FALSE);
  1140.   }
  1141.   read (Handle, &L, 4);
  1142.   if (L != 0x00435341)
  1143.   {
  1144.     printf ("File \"%s\" is not an ASC file !\n", WARNINGFileName);
  1145.     close (Handle);
  1146.     return (FALSE);
  1147.   }
  1148.   read (Handle, &W, 2);
  1149.   if (W != SCREEN_DX)
  1150.   {
  1151.     printf ("Picture in file \"%s\" is not %d chars wide !\n", WARNINGFileName, SCREEN_DX);
  1152.     close (Handle);
  1153.     return (FALSE);
  1154.   }
  1155.   read (Handle, &W, 2);
  1156.   if (W != SCREEN50_DY >> 1)
  1157.   {
  1158.     printf ("Picture in file \"%s\" is not %d chars high !\n", WARNINGFileName, SCREEN50_DY >> 1);
  1159.     close (Handle);
  1160.     return (FALSE);
  1161.   }
  1162.   close (Handle);
  1163.  
  1164.   /* Check <background ASC file> */
  1165.  
  1166.   Handle = _open (BCKFileName, _O_RDONLY);
  1167.   if (Handle == - 1)
  1168.   {
  1169.     printf ("Can't open file \"%s\" !\n", BCKFileName);
  1170.     return (FALSE);
  1171.   }
  1172.   read (Handle, &L, 4);
  1173.   if (L != 0x00435341)
  1174.   {
  1175.     printf ("File \"%s\" is not an ASC file !\n", BCKFileName);
  1176.     close (Handle);
  1177.     return (FALSE);
  1178.   }
  1179.   read (Handle, &W, 2);
  1180.   if (W != SCREEN_DX)
  1181.   {
  1182.     printf ("Picture in file \"%s\" is not %d chars wide !\n", BCKFileName, SCREEN_DX);
  1183.     close (Handle);
  1184.     return (FALSE);
  1185.   }
  1186.   read (Handle, &W, 2);
  1187.   if (W != SCREEN50_DY - 1)
  1188.   {
  1189.     printf ("Picture in file \"%s\" is not %d chars high !\n", BCKFileName, SCREEN50_DY);
  1190.     close (Handle);
  1191.     return (FALSE);
  1192.   }
  1193.   close (Handle);
  1194.  
  1195.   /* Check <window ASC file> */
  1196.  
  1197.   Handle = _open (WINFileName, _O_RDONLY);
  1198.   if (Handle == - 1)
  1199.   {
  1200.     printf ("Can't open file \"%s\" !\n", WINFileName);
  1201.     return (FALSE);
  1202.   }
  1203.   read (Handle, &L, 4);
  1204.   if (L != 0x00435341)
  1205.   {
  1206.     printf ("File \"%s\" is not an ASC file !\n", WINFileName);
  1207.     close (Handle);
  1208.     return (FALSE);
  1209.   }
  1210.   read (Handle, &W, 2);
  1211.   if (W != LDES_DX)
  1212.   {
  1213.     printf ("Picture in file \"%s\" is not %d chars wide !\n", WINFileName, LDES_DX);
  1214.     close (Handle);
  1215.     return (FALSE);
  1216.   }
  1217.   read (Handle, &W, 2);
  1218.   if (W != LDES_DY)
  1219.   {
  1220.     printf ("Picture in file \"%s\" is not %d chars high !\n", WINFileName, LDES_DY);
  1221.     close (Handle);
  1222.     return (FALSE);
  1223.   }
  1224.   close (Handle);
  1225.  
  1226.   /* Check <about ASC file> */
  1227.  
  1228.   Handle = _open (ABOUTFileName, _O_RDONLY);
  1229.   if (Handle == - 1)
  1230.   {
  1231.     printf ("Can't open file \"%s\" !\n", ABOUTFileName);
  1232.     return (FALSE);
  1233.   }
  1234.   read (Handle, &L, 4);
  1235.   if (L != 0x00435341)
  1236.   {
  1237.     printf ("File \"%s\" is not an ASC file !\n", ABOUTFileName);
  1238.     close (Handle);
  1239.     return (FALSE);
  1240.   }
  1241.   read (Handle, &W, 2);
  1242.   if (W != ABOUT_DX)
  1243.   {
  1244.     printf ("Picture in file \"%s\" is not %d chars wide !\n", ABOUTFileName, ABOUT_DX);
  1245.     close (Handle);
  1246.     return (FALSE);
  1247.   }
  1248.   read (Handle, &W, 2);
  1249.   if (W != ABOUT_DY)
  1250.   {
  1251.     printf ("Picture in file \"%s\" is not %d chars high !\n", ABOUTFileName, ABOUT_DY);
  1252.     close (Handle);
  1253.     return (FALSE);
  1254.   }
  1255.   close (Handle);
  1256.  
  1257.   return (TRUE);
  1258. }
  1259.  
  1260. /****************************************************************************/
  1261.  
  1262. main (int argc, char *argv[], char *envp[])
  1263. {
  1264.   BYTE Key, *pString;
  1265.   struct TList *pList;
  1266.   struct TNode *pNode, *pNodeTmp;
  1267.   WORD X, W, Select;
  1268.   BYTE Path[PATH_SIZE];
  1269.  
  1270.   /* Control args */
  1271.  
  1272.   _clearscreen (_GCLEARSCREEN);
  1273.   if (argc != 7)
  1274.   {
  1275.     printf ("Syntax: MPC <Configuration> <Intro> <Warning> <Background> <Window> <About>\n");
  1276.     return (0);
  1277.   }
  1278.   strcpy (CONFileName, argv[1]);
  1279.   strcpy (INTROFileName, argv[2]);
  1280.   strcpy (WARNINGFileName, argv[3]);
  1281.   strcpy (BCKFileName, argv[4]);
  1282.   strcpy (WINFileName, argv[5]);
  1283.   strcpy (ABOUTFileName, argv[6]);
  1284.   if (CheckArgs () == FALSE)
  1285.   {
  1286.     printf ("Syntax: MPC <Configuration> <Intro> <Warning> <Background> <Window> <About>\n");
  1287.     return (0);
  1288.   }
  1289.  
  1290.   /* Initializations */
  1291.  
  1292.   _chdir ("\\");
  1293.   pList = CONSetup ();
  1294.   Select = 0;
  1295.   pNode = pList->Head;
  1296.   Introduction ();
  1297.   DrawList (pNode);
  1298.   DrawSelect (pNode, Select, NULL, 0);
  1299.   Path[0] = '\0';
  1300.   WriteBlockText (Path, PATH_X, PATH_Y, PATH_DX, PATH_DY, COL_PATH, CHR_PATH);
  1301.  
  1302.   /* Main loop */
  1303.  
  1304.   for (;;)
  1305.   {
  1306.     Key = _getch ();
  1307.     switch (Key)
  1308.     {
  1309.       case KEY_RETURN:
  1310.     switch (pNode->Type)
  1311.     {
  1312.       case TYPE_NODE:
  1313.       case TYPE_PICTURE:
  1314.         Execute (pNode, pList);
  1315.         break;
  1316.  
  1317.       case TYPE_PARENT:
  1318.         DrawSelect (NULL, 0, pNode, Select);
  1319.         pList = pList->Pred;
  1320.         pNode = pList->Head;
  1321.         Select = 0;
  1322.         DrawList (pNode);
  1323.         DrawSelect (pNode, Select, NULL, 0);
  1324.         pString = Path + strlen (Path);
  1325.         while (*pString != '\\')
  1326.           pString --;
  1327.         *pString = '\0';
  1328.         WriteBlockText (Path, PATH_X, PATH_Y, PATH_DX, PATH_DY, COL_PATH, CHR_PATH);
  1329.         break;
  1330.  
  1331.       case TYPE_LIST:
  1332.         pString = Path;
  1333.         while (*pString != '\0')
  1334.           pString ++;
  1335.         W = PATH_SIZE - (pString + 1 - Path);
  1336.         if (W != 0)
  1337.         {
  1338.           *pString ++ = '\\';
  1339.           *pString = '\0';
  1340.           if (W -- != 0)
  1341.           {
  1342.         strncpy (pString, pNode->pName, W);
  1343.         *(pString + W) = '\0';
  1344.           }
  1345.         }
  1346.         WriteBlockText (Path, PATH_X, PATH_Y, PATH_DX, PATH_DY, COL_PATH, CHR_PATH);
  1347.         DrawSelect (NULL, 0, pNode, Select);
  1348.         pList = ((struct TNodeLIST *) pNode)->pList;
  1349.         pNode = pList->Head;
  1350.         Select = 0;
  1351.         DrawList (pNode);
  1352.         DrawSelect (pNode, Select, NULL, 0);
  1353.         break;
  1354.  
  1355.       default:
  1356.         break;
  1357.     }
  1358.     break;
  1359.  
  1360.       case KEY_e:
  1361.       case KEY_E:
  1362.     Execute (pNode, pList);
  1363.     break;
  1364.  
  1365.       case KEY_a:
  1366.       case KEY_A:
  1367.     About ();
  1368.     break;
  1369.  
  1370.       case KEY_d:
  1371.       case KEY_D:
  1372.     DrawLDes (pNode);
  1373.     break;
  1374.  
  1375.       case KEY_q:
  1376.       case KEY_Q:
  1377.       case KEY_ESC:
  1378.     Quit (pList);
  1379.     return (0);
  1380.  
  1381.       case 0:
  1382.     Key = _getch ();
  1383.     switch (Key)
  1384.     {
  1385.       case KEY_PUP:
  1386.         pNodeTmp = pNode;
  1387.         for (X = Select; X != 0; X --)
  1388.           pNodeTmp = pNodeTmp->Pred;
  1389.         X = 0;
  1390.         while (pNodeTmp->Pred != NULL)
  1391.         {
  1392.           pNodeTmp = pNodeTmp->Pred;
  1393.           X ++;
  1394.           if (X == LV_DY)
  1395.         break;
  1396.         }
  1397.         if (X != 0)
  1398.         {
  1399.           DrawSelect (NULL, 0, pNode, Select);
  1400.           pNode = pNodeTmp;
  1401.           Select = 0;
  1402.           DrawList (pNode);
  1403.           DrawSelect (pNode, Select, NULL, 0);
  1404.         }
  1405.         else if (Select != 0)
  1406.         {
  1407.           DrawSelect (pNodeTmp, 0, pNode, Select);
  1408.           pNode = pNodeTmp;
  1409.           Select = 0;
  1410.         }
  1411.         break;
  1412.  
  1413.       case KEY_PDOWN:
  1414.         if (pNode->Succ != NULL)
  1415.         {
  1416.           pNodeTmp = pNode;
  1417.           for (X = LV_DY - Select; X != 0; X --)
  1418.           {
  1419.         if (pNodeTmp->Succ == NULL)
  1420.         {
  1421.           DrawSelect (pNodeTmp, LV_DY - X, pNode, Select);
  1422.           pNode = pNodeTmp;
  1423.           Select = LV_DY - X;
  1424.           break;
  1425.         }
  1426.         pNodeTmp = pNodeTmp->Succ;
  1427.           }
  1428.           if (X == 0)
  1429.           {
  1430.         DrawSelect (NULL, 0, pNode, Select);
  1431.         pNode = pNodeTmp;
  1432.         Select = 0;
  1433.         DrawList (pNode);
  1434.         DrawSelect (pNode, Select, NULL, 0);
  1435.           }
  1436.         }
  1437.         break;
  1438.  
  1439.       case KEY_UP:
  1440.         if (Select != 0)
  1441.         {
  1442.           DrawSelect (pNode->Pred, Select - 1, pNode, Select);
  1443.           Select --;
  1444.           pNode = pNode->Pred;
  1445.         }
  1446.         else
  1447.         {
  1448.           if (pNode->Pred != NULL)
  1449.           {
  1450.         pNode = pNode->Pred;
  1451.         DrawList (pNode);
  1452.         DrawSelect (pNode, Select, NULL, 0);
  1453.           }
  1454.         }
  1455.         break;
  1456.  
  1457.       case KEY_DOWN:
  1458.         if (Select != (LV_DY - 1))
  1459.         {
  1460.           if (pNode->Succ != NULL)
  1461.           {
  1462.         DrawSelect (pNode->Succ, Select + 1, pNode, Select);
  1463.         Select ++;
  1464.         pNode = pNode->Succ;
  1465.           }
  1466.         }
  1467.         else
  1468.         {
  1469.           if (pNode->Succ != NULL)
  1470.           {
  1471.         for (W = LV_DY - 2; W != 0; W --)
  1472.           pNode = pNode->Pred;
  1473.         DrawList (pNode);
  1474.         for (W = LV_DY - 1; W != 0; W --)
  1475.           pNode = pNode->Succ;
  1476.         DrawSelect (pNode, Select, NULL, 0);
  1477.           }
  1478.         }
  1479.         break;
  1480.  
  1481.       default:
  1482.         break;
  1483.     }
  1484.     break;
  1485.  
  1486.       default:
  1487.     break;
  1488.     }
  1489.   }
  1490. }
  1491.